package com.sgb.alimaplibrary.widget;

import android.content.Context;
import android.content.res.TypedArray;
import android.os.Bundle;
import android.text.TextUtils;
import android.util.AttributeSet;

import androidx.annotation.Nullable;
import androidx.lifecycle.Lifecycle;
import androidx.lifecycle.MutableLiveData;

import com.amap.api.maps.MapView;
import com.amap.api.maps.model.LatLng;
import com.amap.api.maps.model.Marker;
import com.amap.api.maps.model.MarkerOptions;
import com.amap.api.services.core.PoiItem;
import com.amap.api.services.core.SuggestionCity;
import com.sgb.alimaplibrary.MapMarkerTools;
import com.sgb.alimaplibrary.MapPoiTools;
import com.sgb.alimaplibrary.MarkerEntity;
import com.sgb.alimaplibrary.R;
import com.sgb.alimaplibrary.entity.LocationEntity;

import java.util.ArrayList;
import java.util.List;

/**
 * 自定义地图显示UI
 */
public class MapMarkerView extends MapView {

    private Context mContext;
    private MapView mMapView;//当前地图承载布局
    public MapMarkerTools mapMarkerTools;//基础地图工具
    private LatLng mFinalLatLng = new LatLng(0.0, 0.0); //定位成功的经纬度
    private String address = "";//定位位置的详细地址
    private List<MarkerEntity> poiItemList = new ArrayList<>();//地图Marker标记集合
    private CallBack callBack;//与使用界面的交互回调
    private boolean isSearchPoi;//是否需要初始化poi搜索功能
    private MapPoiTools mPoiSearch;//poi搜索工具
    private List<PoiItem> poiItems = new ArrayList<>();
    private boolean isMyLocation;//要不要在地图上显示定位当前位置的按钮
    private boolean isOpenLocation;//是否默认开启定位
    private int mapLocationStyle;//当前定位标记在地图上的图片样式
    MutableLiveData<LocationEntity> mutableLiveData;
    private boolean isMyMarker = false; //是否返回当前省市区的经纬度
    private int zoomPosition = 10;//4-40 ,值越大越详细


    public String getCityName() {
        return mPoiSearch.getCityName();
    }


    public abstract static class CallBack {

        /**
         * 初始化完成
         */
        public void initMap(){

        }

        /**
         * Marker的标记点点击回调
         *
         * @param pos
         */
        public abstract void onMarkerClick(int pos, String title);

        public void onMarkerClick(int pos, String title, Marker marker) {
        }

        /**
         * 当前定位成功回调
         *
         * @param Lat
         * @param Log
         * @param string
         */
        public abstract void onLocation(Double Lat, Double Log, String string);

        /**
         * 通过经纬度反地理编码返回的地址
         *
         * @param Lat
         * @param Log
         * @param string
         */
        public void onRegeocodeSearched(Double Lat, Double Log, String string) {
        }

        /**
         * 通过经纬度反地理编码返回的地址
         *
         * @param Lat
         * @param Log
         * @param string
         */
        public void getAddress(Double Lat, Double Log, String string) {
        }

        public void failure() {
        }

        public void getPoiItems(List<PoiItem> poiItemList) {
        }
    }

    public MapMarkerView(Context context) {
        this(context, null);
    }

    public MapMarkerView(Context context, @Nullable AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public MapMarkerView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        this.mContext = context;
        TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.MapMarkerView);
        isSearchPoi = typedArray.getBoolean(R.styleable.MapMarkerView_is_poi, false);
        isMyLocation = typedArray.getBoolean(R.styleable.MapMarkerView_is_my_loction, false);
        isOpenLocation = typedArray.getBoolean(R.styleable.MapMarkerView_is_open_loction, true);
        mapLocationStyle = typedArray.getResourceId(R.styleable.MapMarkerView_map_location_style, 0);
        typedArray.recycle();
    }

    /**
     * 初始化地图
     *
     * @param savedInstanceState
     * @param lifecycle
     * @param callBack
     */
    public void initMap(Bundle savedInstanceState, Lifecycle lifecycle, CallBack callBack) {
        this.callBack = callBack;
        mapMarkerTools = new MapMarkerTools(mContext, lifecycle, isOpenLocation);
        initMapView(savedInstanceState);
        if (isSearchPoi) {
            initPoiSearch();
        }

        if (callBack !=null ){
            callBack.initMap();
        }
    }

    /**
     * 初始化地图
     *
     * @param savedInstanceState
     * @param lifecycle
     * @param callBack
     */
    public void initMap(Bundle savedInstanceState, Lifecycle lifecycle,int zoomPosition, CallBack callBack) {
        this.zoomPosition = zoomPosition;
        initMap(savedInstanceState,lifecycle,callBack);
    }

    /**
     * 初始化地图
     *
     * @param savedInstanceState
     * @param lifecycle
     * @param mutableLiveData    MutableLiveData<LocationEntity> mutableLiveData = new MutableLiveData<LocationEntity>();
     *                           mutableLiveData.observe(this, new Observer<LocationEntity>() {
     * @Override public void onChanged(LocationEntity locationEntity) {
     * String tag = locationEntity.getTag();
     * switch (tag){
     * case "onLocation":
     * binding.tvAddressName.setText(locationEntity.getAddress());
     * latitude = locationEntity.getLatitude();
     * longitude = locationEntity.getLongitude();
     * initFilterData();
     * break;
     * case "onMarkerClick":
     * showMapPopWindow(locationEntity.getPos());
     * break;
     * }
     * }
     * });
     * binding.mMapView.initMap(savedInstanceState, getLifecycle(),mutableLiveData);
     */
    public void initMap(Bundle savedInstanceState, Lifecycle lifecycle, MutableLiveData<LocationEntity> mutableLiveData) {
        this.mutableLiveData = mutableLiveData;
        mapMarkerTools = new MapMarkerTools(mContext, lifecycle, isOpenLocation);
        initMapView(savedInstanceState);
        if (isSearchPoi) {
            initPoiSearch();
        }

        if (callBack !=null ){
            callBack.initMap();
        }
    }

    /**
     * 显示基础地图初始化
     *
     * @param savedInstanceState
     */
    private void initMapView(Bundle savedInstanceState) {
        mMapView = this;
//        if (mMapView.getChildCount() >= 2){
//            View child = mMapView.getChildAt(1);
//            if (child != null && (child instanceof ImageView || child instanceof ZoomControls)) {
//                child.setVisibility(View.INVISIBLE);
//            }
//        }
        if (isMyLocation) {
            mapMarkerTools.setMapLocationStyle(true);
        }

        if (mapLocationStyle != 0) {
            mapMarkerTools.setMapLocationStyleBitmap(mapLocationStyle);
        }

        mapMarkerTools.init(savedInstanceState, mMapView,zoomPosition);
        mapMarkerTools.setMarkerClick(new MapMarkerTools.MarkerClick() {
            @Override
            public void onMarkerClick(int pos, String title) {
                showMarkerView(pos, title, null);
            }

            @Override
            public void onMarkerClick(int pos, String title, Marker marker) {
                super.onMarkerClick(pos,title,marker);
                showMarkerView(pos, title, marker);
            }

            @Override
            public void onLocationChanged(Double Lat, Double Log, String string) {
//        mutableLiveData.postValue(string);
                try {
                    if (mutableLiveData != null) {
                        LocationEntity locationEntity = new LocationEntity("onLocation", Lat, Log, string);
                        mutableLiveData.postValue(locationEntity);
                    }
                    if (mFinalLatLng.latitude != 0 && mFinalLatLng.longitude != 0) return;
                    if (callBack != null) {
                        callBack.onLocation(Lat, Log, string);
                    }
                    mFinalLatLng = new LatLng(Lat, Log);
                    //详细地址
                    address = TextUtils.isEmpty(string) ? "" : string;
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }

            @Override
            public void getAddress(Double Lat, Double Log, String address) {
                super.getAddress(Lat,Log,address);
                if (callBack != null) {
                    callBack.getAddress(Lat, Log, address);
                }
                if (mutableLiveData != null) {
                    LocationEntity locationEntity = new LocationEntity("getAddress", Lat, Log, address);
                    mutableLiveData.postValue(locationEntity);
                }
            }

            @Override
            public void failure() {
                super.failure();
                if (callBack != null) {
                    callBack.failure();
                }
            }
        });
    }

    /**
     * Marker点击事件
     *
     * @param pos
     * @param title
     */
    private void showMarkerView(int pos, String title, Marker marker) {
        if (callBack != null) {
            int k = -1;
            if (poiItemList.size() == 0) {
                k = pos;
                if (marker != null) {
                    callBack.onMarkerClick(k, title, marker);
                    return;
                }
                callBack.onMarkerClick(k, title);
                return;
            }

            for (MarkerEntity markerEntity : poiItemList) {
                k++;
                if (markerEntity.getTitle().equals(title)) {
                    if (marker != null) {
                        callBack.onMarkerClick(k, title, marker);
                        return;
                    }
                    callBack.onMarkerClick(k, title);
                    return;
                }
            }

            if (mutableLiveData != null) {
                LocationEntity locationEntity = new LocationEntity("onMarkerClick", 0, 0, "");
                locationEntity.setPos(pos);
                mutableLiveData.postValue(locationEntity);
            }
        }
    }

    /**
     * 清空地图上的，marker 标记，然后重新添加
     *
     * @param markerEntityList
     */
    public void setMarkerData(List<MarkerEntity> markerEntityList) {
        poiItemList.clear();
        poiItemList.addAll(markerEntityList);
        mapMarkerTools.setData(getMarkerOptions(markerEntityList), true);
        mapMarkerTools.zoomToSpan();
    }

    /**
     *
     * @param markerEntityList
     */
    public void updateMarkerDataPick(List<MarkerEntity> markerEntityList,boolean isClear,LatLng latLng) {
        if(markerEntityList == null){
            mapMarkerTools.setDataPick(null, false,null);
            return;
        }
        if(isClear){
            poiItemList.clear();
        }
        poiItemList.addAll(markerEntityList);
        mapMarkerTools.setDataPick(markerEntityList, false,latLng);
    }

    /**
     *
     * @param markerEntityList
     */
    public void updateMarkerDataPick(List<MarkerEntity> markerEntityList,boolean isClear) {
        if(markerEntityList == null){
            mapMarkerTools.setDataPick(null, false,null);
            return;
        }
        if(isClear){
            poiItemList.clear();
        }
        poiItemList.addAll(markerEntityList);
        mapMarkerTools.setDataPick(markerEntityList, false,markerEntityList.get(0).getLatLng());
    }

    /**
     * 清空地图上的，marker 标记，然后重新添加
     *
     * @param markerEntityList
     */
    public void setMarkerDataPick(List<MarkerEntity> markerEntityList,LatLng latLng) {
        poiItemList.clear();
        poiItemList.addAll(markerEntityList);
        mapMarkerTools.setDataPick(markerEntityList, false,latLng);
    }

    /**
     * 不清除地图原有标记，新增更多标记
     *
     * @param markerEntityList
     */
    public void addMarkerData(List<MarkerEntity> markerEntityList) {
        poiItemList.addAll(markerEntityList);
        mapMarkerTools.addAllMarker(getMarkerOptions(markerEntityList));
        mapMarkerTools.zoomToSpan();
    }

    /**
     * 将标记的经纬度集合转换为地图可识别标点
     *
     * @param markerEntityList
     * @return
     */
    private List<MarkerOptions> getMarkerOptions(List<MarkerEntity> markerEntityList) {
        List<MarkerOptions> markerOptionsList = new ArrayList<>();
        for (MarkerEntity markerEntity : markerEntityList) {
            markerOptionsList.add(mapMarkerTools.getMarkerOptions(markerEntity));
        }
        return markerOptionsList;
    }

    /**
     * 初始化POi搜索
     */
    private void initPoiSearch() {
        mPoiSearch = MapPoiTools.newInstance(mContext, mMapView.getMap(), new MapPoiTools.CalllBack() {
            @Override
            public void showSuggestCity(List<SuggestionCity> list, List<PoiItem> pois, int currentPage) {
                //根据关键字通过POI搜索返回数据
                if (currentPage == 0) {
                    poiItems.clear();
                }
                poiItems.addAll(pois);
                if (callBack != null) {
                    callBack.getPoiItems(poiItems);
                }
                LatLng latLonPoint = new LatLng(poiItems.get(0).getLatLonPoint().getLatitude(), poiItems.get(0).getLatLonPoint().getLongitude());
                if (isMyMarker){
                    if (callBack != null) {
                        callBack.getAddress(latLonPoint.latitude, latLonPoint.longitude,poiItems.get(0).getBusinessArea() );
                    }
                    return;
                }
                mapMarkerTools.addAllMarkerToMap(0, true, poiItems, latLonPoint);
                showMarkerView(0, pois.get(0).getTitle(), null);
            }

            @Override
            public void onRegeocodeSearched(String suggestionCityList) {
                //根据经纬度反地理编码返回地址信息
                if (callBack != null) {
                    callBack.onRegeocodeSearched(mFinalLatLng.latitude, mFinalLatLng.longitude, suggestionCityList);
                }
            }
        });
    }

    public void setMyLocation(Double currentLat, Double currentLong, int icon) {
        if (mapMarkerTools != null){
            mapMarkerTools.setMyLocation(currentLat, currentLong, icon);
        }

    }

    /**
     * 移动到当前点为中心的视图界面
     *
     * @param latLng
     */
    public void zoomToSpan(LatLng latLng) {
        if (mapMarkerTools != null){
            mapMarkerTools.zoomToSpan(latLng);
        }

    }

    public List<PoiItem> getPoiItems() {
        return poiItems;
    }

    public PoiItem getPoiItem(String tile) {
        for (PoiItem poiItem : poiItems) {
            if (poiItem.equals(tile)) {
                return poiItem;
            }
        }
        return null;
    }

    /**
     * 设置地图可以点击选取位置
     */
    public void setMapClick() {
        mapMarkerTools.setMapClick();
    }

    /**
     * 通过关键字搜索
     *
     * @param keyWord
     * @param cityName
     */
    public void setPoiSearch(String keyWord, String cityName) {
        if (mPoiSearch != null)
            mPoiSearch.doSearchQuery(keyWord, cityName);
    }

    /**
     * 通过关键字搜索
     *
     * @param keyWord
     * @param cityName
     */
    public void setPoiSearch(String keyWord, String cityName,boolean isMyMarker) {
        this.isMyMarker = isMyMarker;
        if (mPoiSearch != null)
            mPoiSearch.doSearchQuery(keyWord, cityName);
    }

    /**
     * 通过经纬度来获取详细地址信息
     *
     * @param latitude
     * @param longtitude
     */
    public void getLatLotExtra(double latitude, double longtitude) {
        if (latitude != 0 && longtitude != 0) {
            mFinalLatLng = new LatLng(latitude, longtitude);
            mapMarkerTools.setMyLocation(latitude, longtitude);
            if (mPoiSearch == null){
                initPoiSearch();
            }
            if (mPoiSearch != null) {
                mPoiSearch.latlotSearchQuery(mFinalLatLng);
            }
        }
    }

    public void setMarkerIcon(int index, boolean isShowText) {
        if (mPoiSearch != null) {
            mPoiSearch.setMarkerIcon(index, isShowText);
        }
    }

    public void deactivate() {
        mapMarkerTools.deactivate();
    }


    public List<Marker> getMapScreenMarkers() {
        if (mapMarkerTools == null) {
            return this.mMapView.getMap().getMapScreenMarkers();
        }
        return mapMarkerTools.getMapScreenMarkers();
    }

    public Marker getMapScreenMarker(String title) {
        for (Marker marker : getMapScreenMarkers()) {
            if (title.equals(marker.getTitle())) {
                return marker;
            }
        }
        return null;
    }

    public MarkerOptions getMapMarkerPick(String title) {
        if (mapMarkerTools != null) {
            for (MarkerOptions markerOptions : mapMarkerTools.getMapMarkersPick()) {
                if (title.equals(markerOptions.getTitle())) {
                    return markerOptions;
                }
            }
        }
        return null;
    }
}
